package com.jinke.api.modules.app.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.annotation.ApiIdempotence;
import com.jinke.api.common.api.CommonPage;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.common.constant.TASMSConstants;
import com.jinke.api.common.constraint.EncryptType;
import com.jinke.api.common.domain.tasms.TASMSSendSMSDTO;
import com.jinke.api.common.domain.tasms.TASMSSendSMSResponse;
import com.jinke.api.common.util.OKHttpRetryRequestUtil;
import com.jinke.api.modules.app.config.SendCodeManager;
import com.jinke.api.modules.app.config.TASMSService;
import com.jinke.api.modules.app.controller.param.UserRegisterParam;
import com.jinke.api.modules.app.request.UserUpdateRequest;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.util.IdWorkerUtil;
import com.jinke.api.modules.app.util.InvitationCodeUtil;
import com.jinke.api.modules.app.util.OssUtil;
import com.jinke.api.modules.app.util.SmsUtil;
import com.jinke.api.modules.ums.dto.ParcelTemplateAddDto;
import com.jinke.api.modules.ums.dto.ParcelTemplateUpdateDto;
import com.jinke.api.modules.ums.dto.UpdateAdminPasswordParam;
import com.jinke.api.modules.ums.dto.UpdateUserPasswordParam;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.model.UmsResource;
import com.jinke.api.modules.ums.model.UmsRole;
import com.jinke.api.modules.ums.model.UmsRoleResourceRelation;
import com.jinke.api.modules.ums.request.SendCodeRequest;
import com.jinke.api.modules.ums.request.UserChannelRequest;
import com.jinke.api.modules.ums.service.*;
import com.jinke.api.modules.ums.util.UserUtil;
import com.jinke.api.modules.ums.vo.ParcelTemplateListVo;
import com.jinke.api.modules.ums.vo.UmsAdminVO;
import com.jinke.api.modules.ums.vo.UserChannelVO;
import com.jinke.api.security.util.AdminUserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.security.Principal;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台用户管理
 * Created by macro on 2018/4/26.
 */
@Controller
@Api(tags = "UserController")
@Tag(name = "平台用户", description = "平台用户")
@RequestMapping("/user")
@Slf4j
public class UserController {
    @Autowired
    private UmsAdminService adminService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource
    private OssUtil ossUtil;
    @Autowired
    private UmsResourceService umsResourceService;
    @Autowired
    private UmsRoleResourceRelationService umsRoleResourceRelationService;
    @Resource
    private UmsAdminService umsAdminService;

    @Autowired
    private ChannelService channelService;
    @Autowired
    private SendCodeManager manager;
    @Resource
    private OrderService orderService;

    @Resource
    private IParcelTemplateService iParcelTemplateService;
    @Resource
    private TASMSService tasmsService;

    @ApiOperation("上传头像")
    @PostMapping(value = "/upload/head")
    @ResponseBody
    public CommonResult UploadHead(@RequestParam("file") MultipartFile file) {
        String url = ossUtil.uploadHead(file);
        if (!url.equals("")) {
            Integer userId = AdminUserUtil.getUserId();
            adminService.update(new LambdaUpdateWrapper<UmsAdmin>().eq(UmsAdmin::getId, userId).set(UmsAdmin::getIcon, url));
            return CommonResult.success();
        } else {
            return CommonResult.failed();
        }
    }

    @ApiOperation(value = "获取当前登录用户信息")
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult getAdminInfo(Principal principal) {
        if (principal == null) {
            return CommonResult.unauthorized(null);
        }
        String username = principal.getName();
        UmsAdmin umsAdmin = adminService.getAdminByKeyword(username);
        UmsAdminVO umsAdminVO = new UmsAdminVO();
        BeanUtils.copyProperties(umsAdmin, umsAdminVO);

        List<UmsRole> roleList = adminService.getRoleList(umsAdmin.getId());
        if (CollUtil.isNotEmpty(roleList)) {
            List<String> roles = roleList.stream().map(x -> {
                return x.getId().toString();
            }).collect(Collectors.toList());
            umsAdminVO.setRoles(roles);

            List<Integer> roleIds = roleList.stream().map(x -> {
                return x.getId();
            }).collect(Collectors.toList());
            Set<Integer> sourceIds = umsRoleResourceRelationService.list(new LambdaQueryWrapper<UmsRoleResourceRelation>()
                            .in(UmsRoleResourceRelation::getRoleId, roleIds))
                    .stream().map(UmsRoleResourceRelation::getResourceId).filter(Objects::nonNull).collect(Collectors.toSet());
            if (CollectionUtil.isNotEmpty(sourceIds)) {
                List<UmsResource> umsResources = umsResourceService.list(new LambdaQueryWrapper<UmsResource>()
                        .in(UmsResource::getId, sourceIds)
                        .isNotNull(UmsResource::getCode)
                        .select(UmsResource::getCode));
                umsAdminVO.setResources(umsResources);
            }
            //计算用户申请退款订单中的金额
            umsAdminVO.setRefundAmount(orderService.sumRefundAmountByUserId(umsAdmin.getId()));
        }
        return CommonResult.success(umsAdminVO);
    }

    @ApiOperation("修改用户信息")
    @RequestMapping(value = "/update/", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult update(@RequestBody UserUpdateRequest admin) {
        UmsAdmin umsAdmin = UserUtil.getUserInfo();
        UmsAdmin tmp = new UmsAdmin();
        BeanUtils.copyProperties(admin, tmp);
        boolean success = adminService.update(umsAdmin.getId(), tmp);
        if (success) {
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }

    @ApiOperation("修改用户密码")
    @RequestMapping(value = "/updatePassword", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult updatePassword(@Validated @RequestBody UpdateUserPasswordParam updatePasswordParam) {

        UmsAdmin umsAdmin = UserUtil.getUserInfo();
        UpdateAdminPasswordParam updateAdminPasswordParam = new UpdateAdminPasswordParam();
        BeanUtils.copyProperties(updatePasswordParam, updateAdminPasswordParam);
        updateAdminPasswordParam.setUsername(umsAdmin.getUsername());
        int status = adminService.updatePassword(updateAdminPasswordParam);
        if (status > 0) {
            return CommonResult.success(status);
        } else if (status == -1) {
            return CommonResult.failed("提交参数不合法");
        } else if (status == -2) {
            return CommonResult.failed("找不到该用户");
        } else if (status == -3) {
            return CommonResult.failed("旧密码错误");
        } else {
            return CommonResult.failed();
        }
    }

    @ApiOperation(value = "用户注册")
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult register(@Validated @RequestBody UserRegisterParam umsAdminParam) {
        UmsAdmin umsAdmin = new UmsAdmin();
        BeanUtils.copyProperties(umsAdminParam, umsAdmin);
        umsAdmin.setCreateTime(new Date());
        umsAdmin.setStatus(0);
        umsAdmin.setProfitRate(BigDecimal.valueOf(1.0));
        //
        umsAdmin.setBalance(BigDecimal.valueOf(0));

        String userName = umsAdminParam.getLastName() + " " + umsAdminParam.getFirstName();
        umsAdmin.setRealName(userName);
        umsAdmin.setUsername(umsAdminParam.getEmail());
        umsAdmin.setInvitationCode(InvitationCodeUtil.create());


        //查询是否有相同用户名的用户
        List<UmsAdmin> umsAdminList = adminService.list(new LambdaQueryWrapper<UmsAdmin>()
                .eq(UmsAdmin::getUsername, umsAdmin.getUsername()));
        if (CollectionUtil.isNotEmpty(umsAdminList)) {
            return CommonResult.failed("The username already exists");
        }
        //判断邮箱是否重复
        UmsAdmin emailUser = adminService.lambdaQuery().eq(UmsAdmin::getEmail, umsAdminParam.getEmail()).one();
        if (ObjectUtils.isNotEmpty(emailUser)) {
            return CommonResult.failed("The email already exists");
        }
        //判断电话号码是重复
        UmsAdmin phoneUser = adminService.lambdaQuery().eq(UmsAdmin::getPhone, umsAdminParam.getPhone()).one();
        if (ObjectUtils.isNotEmpty(phoneUser)) {
            return CommonResult.failed("The phone already exists");
        }

        // 绑定销售
        String invitationCode = umsAdminParam.getInvitationCode();
        if (StringUtils.isNotBlank(invitationCode)) {
            UmsAdmin seller = umsAdminService.getOne(new LambdaQueryWrapper<UmsAdmin>().eq(UmsAdmin::getInvitationCode, invitationCode));
            if (seller == null) {
                return CommonResult.failed("Invalid invitation code");
            }
            Integer sellerId = seller.getSellerId();
            if (sellerId == null) {
                sellerId = seller.getId();
            }
            umsAdmin.setSellerId(sellerId);
        }

        //将密码进行加密操作
        String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());
        umsAdmin.setPassword(encodePassword);

        // 验证短信验证码
        String phone = umsAdminParam.getPhone();
        String countryCode = umsAdminParam.getCountryCode();
        if (countryCode.startsWith("86") || countryCode.startsWith("+86")) {
            String smsCode = umsAdminParam.getSmsCode();
            SendCodeManager.MatchResult result = manager.doMatchCode(countryCode + phone, smsCode);
            if (!result.isMatch()) {
                return CommonResult.failed(result.getReason());
            }
        }
        //保存用户信息
        adminService.save(umsAdmin);
        // 分配角色
        adminService.updateRole(umsAdmin.getId(), Arrays.asList(1));

        return CommonResult.success();
    }


    @ApiOperation("获取用户运输服务")
    @RequestMapping(value = "/user-channel", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<UserChannelVO>> getUserChannel(@Validated UserChannelRequest request) {
        Integer userId = AdminUserUtil.getUserId();
        request.setUserId(userId);
        return channelService.getUserChannel(request);
    }

    @PostMapping("/code/send")
    @ApiOperation(value = "验证码发送", notes = "验证码发送")
    @ResponseBody
    public CommonResult sendCode(@RequestBody @Valid SendCodeRequest request) {
        String phone = request.getPhone();
        String toSend = request.getCountryCode() + phone;
        String reason = manager.addCanSendCtrl(toSend);
        if (StringUtils.isNotEmpty(reason)) {
            return CommonResult.failed(reason);
        }
        //验证码
        String verityCode = IdWorkerUtil.getCode();

        boolean b = SmsUtil.sendSms(toSend, verityCode);
        //新旧发短信切换，目前老板还没说要换
        //boolean b = tasmsService.sendSms(toSend, verityCode);
        if (!b) {
            log.error("验证码发送失败"+verityCode+"-"+toSend);

            return CommonResult.failed("发送失败");
        }else {
            log.error("验证码发送成功"+verityCode+"-"+toSend);
        }
        //添加控制
        manager.addInterValCtrl(toSend, verityCode);
        manager.addValidityCtrl(toSend, verityCode);
        return CommonResult.success();
    }




    /**
     * 包裹模板列表
     */
    @RequestMapping(value = "/template/list", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<ParcelTemplateListVo>> getList(String keyWord) {
        return iParcelTemplateService.getListByUserId(keyWord);
    }

    /**
     * 编辑包裹模板信息
     */
    @RequestMapping(value = "/template/update", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult updateById(@Validated @RequestBody ParcelTemplateUpdateDto dto) {
        return iParcelTemplateService.updateByDto(dto);
    }

    /**
     * 增加包裹模板
     */
    @RequestMapping(value = "/template/add", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult add(@Validated @RequestBody ParcelTemplateAddDto dto) {
        return iParcelTemplateService.add(dto);
    }


}
